home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
134_01
/
ctoa.c
< prev
next >
Wrap
Text File
|
1985-08-19
|
20KB
|
905 lines
/* CTOA -- BDS `C' CRL-to-ASM postprocessor- part 1. */
/*
Kevin B. Kenny
729-A E. Cochise Dr.
Phoenix, AZ 85020
*/
/* Copyright (c) 1983 by Kevin B. Kenny
Released to the BDS `C' Users' Group for non-commercial distribution
only. */
/* This program is a utility that generates assembly language (.CSM)
source files for BDS `C' programs. It accepts the .CRL file for the
object instructions, the .CDB file for the symbols, and the .C source
file for commentary. From these, it produces a .CSM file that generate
the same object code.
Syntax:
ctoa source_file [>output_file]
*/
#include <bdscio.h>
#include <dio.h>
#include <cmdutil.h>
#include "ctoatbls.h"
#include "ctoa.h"
#define TITLE "CTOA version 83-11-11 copyright (c) 1983 by Kevin Kenny.\n"
/* Main program */
main (argc, argv)
int argc;
char * * argv;
{
/* Check command syntax */
dioinit (&argc, argv);
if (argc != 2) {
fprintf (STD_ERR, "Usage: ctoa filename [>outfile]\n");
quit ();
}
fprintf (STD_ERR, TITLE);
/* Pick up the source file name, and open the source */
strcpy (srcfnam, argv [1]);
if (fopen (srcfnam, srcfile) == ERROR) {
fprintf (STD_ERR, "Can't open %s: %s\n", srcfnam,
errmsg (errno ()));
quit ();
}
/* Acquire the opcode table */
opc_tabl = opctabl ();
/* Go get the .CRL and .CDB files */
initcdb ();
initcrl ();
/* Process the content of the .CRL file */
proccrl ();
/* Flush any remaining text from the source file, and close it. */
while (!seof) sscan ();
printf ("\n\n\tend\n");
fclose (srcfile);
if (cdbopen) cclose (cdbfile);
/* Flush out directed I/O */
dioflush ();
}
/* Set up processing of the .CRL file for object text */
initcrl() {
/* Get the .CRL file name */
strcpy (crlfnam, srcfnam);
makeext (crlfnam, "CRL");
/* Open the .CRL file, and read in the directory from it */
tcopen (crlfile, crlfnam);
tcseek (crlfile, 0, CABS, crlfnam);
tcread (crlfile, crldir, sizeof crldir, crlfnam);
/* Print a heading on the CSM file indicating the file name and
compilation options. */
printf (";\t%s\tBDS `C' object code of %s\n", crlfnam, srcfnam);
printf (";\t\t\tCompilation options:");
if (havecdb) printf (" -k");
if (crldir.crleflag == 0xBD)
printf (" -e %04x", crldir.crleloc);
printf ("\n");
printf (";\t\t\tExternals use %d (0x%04x) bytes.\n",
crldir.crlelen, crldir.crlelen);
printf ("\n\tMACLIB\t<BDS.LIB>\n\n");
if (crldir.crleflag == 0xBD)
printf ("SYS$EXTFLAG\tSET\t0BDH\nSYS$EXTADDR\tSET\t0%04xH\n",
crldir.crleloc);
printf ("SYS$EXTSIZE\tSET\t0%04xH\n\n", crldir.crlelen);
/* Print non-library-defined CCC symbols on the .CSM file. */
initccc ();
}
/* Process the functions on a .CRL file */
proccrl () {
union { /* .CRL directory pointer */
char * c;
int * i;
} dirp;
/* Point dirp to the start of the directory */
dirp.c = & (crldir.crldtext);
/* Walk through the directory, doing functions one by one */
for (;;) {
strcpy70 (fname, dirp.c); /* Get function name */
if (!*fname) break; /* Return if end of file */
dirp.c += strlen (fname); /* Advance directory pointer */
faddr = *dirp.i++; /* Get function address */
procfunc (); /* Process the function */
}
cclose (crlfile); /* All done; close file */
}
/* Do one function from a .CRL file */
procfunc () {
/* Announce ourselves */
fprintf (STD_ERR, "; Processing the %s function:\n", fname);
/* Find the function on the source and .CDB files. */
sfunct (fname);
cdbfunct (fname);
/* Put the FUNCTION statement on the .CSM file */
printf ("\n\tFUNCTION\t%s\n\n", fname);
/* Process the external references from the function */
procexts ();
/* Output the stack frame layout */
doframe ();
/* Read in the function text and relocation */
if (!readfunc ()) {
fprintf (STD_ERR, ";*** Function is too large to analyze.\n");
fprintf (STD_ERR, ";*** Break it up and try again.\n");
}
else {
/* Construct the label table */
bldlbtab ();
/* Output the code */
asmcode ();
/* Get rid of allocated memory */
freefunc ();
}
/* Find the end of the function on the source */
sendfn ();
/* Put the ENDFUNC statement on the .CSM file */
printf (";\n\tENDFUNC\t\t%s\n;\n", fname);
}
/* Process the external reference directory from a function on the
.CRL file */
procexts () {
int extdlen; /* Length of the external directory */
char syname [NAMLEN]; /* Name of an external symbol */
char * xnamp; /* Pointer to current char in name */
/* Position to the start of the function's external directory */
extdlen = 0;
tcseek (crlfile, faddr, CABS, crlfnam);
nexts = 0; /* No externals yet. */
/* Read externals from the file */
for (;;) {
xnamp = & syname;
tcread (crlfile, xnamp, 1, crlfnam); ++extdlen;
/* Get first byte of external name */
if (syname [0] == '\0') break;
/* If it's zero, we're done. */
while ((*xnamp & 0x80) == 0) {
tcread (crlfile, ++xnamp, 1, crlfnam); ++extdlen;
} /* Read the rest of the symbol */
*xnamp &= 0x7F; /* Strip the 7th bit from last char */
*++xnamp = 0; /* Add null terminator */
printf ("\tEXTERNAL\t%s\n", syname);
/* Put EXTERNAL statement on .CSM */
strcpy (xname [nexts++], syname);
/* Install name in table */
}
/* End of external directory */
printf (";\n");
ftaddr = faddr + extdlen + 2; /* Find function text */
}
/* Read the text and relocation of a function */
readfunc () {
/* Read in the length word for the function text */
tcseek (crlfile, ftaddr-2, CABS, crlfnam);
tcread (crlfile, &ftlen, 2, crlfnam);
/* Get space for the function text, and read it in. */
if ((ftext = alloc (ftlen)) == NULL) return (FALSE);
tcread (crlfile, ftext, ftlen, crlfnam);
/* Read in the size of the relocation info */
tcread (crlfile, &frlen, 2, crlfnam);
/* Read in the relocation data itself */
if ((freloc = alloc (2 * frlen)) == NULL) {
free (ftext);
return (FALSE);
}
tcread (crlfile, freloc, 2 * frlen, crlfnam);
/* Tell the user what happened */
fprintf (STD_ERR, ";\t%d (0x%04x) bytes of text, ", ftlen, ftlen);
fprintf (STD_ERR, "%d relocation directives,\n", frlen);
fprintf (STD_ERR, ";\t%d external functions", nexts);
if (havecdb) {
fprintf (STD_ERR, ", %d external variables,\n", nextvs);
fprintf (STD_ERR, ";\t%d auto variables, %d formal parameters, ",
nautvs, nparvs);
fprintf(STD_ERR, "frame size is %d (0x%04x)\n", framesize, framesize);
}
else fprintf (STD_ERR, "\n");
return (TRUE);
}
/* Make the label table for a function */
bldlbtab () {
nlabs = 0; /* Clear out the label table */
pass1 = TRUE; /* We're doing the label pass */
dotext (); /* Analyze text for line #s. */
doreloc (); /* Get other labels from relocation */
}
/* Make the assembly code for a function */
asmcode () {
pass1 = FALSE; /* We're doing the code pass */
dotext (); /* Output the instructions */
dospool (); /* Output the string pool */
}
/* Walk through the instructions for a function */
dotext () {
char * label; /* Label on the current word */
struct opc_entry * opcent;
/* Set up the initial location counter past the external header */
if (nexts == 0) locctr = 0;
else locctr = 3 * nexts + 3;
retaddr = ftlen; /* Dummy up a return address */
highcode = 0; /* Dummy up a high transfer address */
/* Walk through the instruction sequence */
while (locctr < retaddr) {
/* Look up the opcode */
opcode = ftext [locctr];
for ( opcent = opc_tabl;
(opcode & opcent -> opc_mask) != opcent -> opc_val;
++opcent) ;
/* In code pass, output the opcode, and any label that
may be needed. */
if (!pass1) {
if ((label = findlab (locctr)) != NULL)
printf ("\n%s:", label);
if (opcent -> opc_type != OP_RST6)
printf ("\t%s", opcent -